/*

Summary:
Macros to define a enum type whose value's name doesn't 
pollute the global namespace.

Remark:
Enum types defined with ZafEnum should be used in this
way: [EnumType]::[EnumValue].

Enum types defined with ZafFlagEnum is the same with 
those defined with ZafEnum, except that the enum values
can be calculated with ~ | & ^ operator.

Version:
0.0.1

LastUpdatedDate:
2012-09-28

CreatedDate:
2012-09-28

*/


#pragma once


#define __Zaf_Enum_CompareOperatorDefine__(op, type)       \
bool operator##op(type rhs) const {                        \
	return m_enumValue op rhs.m_enumValue;                 \
}                                                          \
bool operator##op(type##Enum rhs) const {                  \
	return m_enumValue op rhs;                             \
}



#define __Zaf_Enum_EnumClassDefine__(name, type)           \
class name {                                               \
public:                                                    \
	enum name##Enum;                                       \
	name() : m_enumValue((name##Enum)0) { }                \
	name(const name& rhs)                                  \
		: m_enumValue(rhs.m_enumValue) { }                 \
	name(name##Enum value) : m_enumValue(value) { }        \
	name operator=(name rhs) {                             \
		m_enumValue = rhs.m_enumValue;                     \
		return *this;                                      \
	}                                                      \
	explicit name(type rawType) :                          \
		m_enumValue((name##Enum)rawType) { }               \
	operator name##Enum() { return m_enumValue; }          \
	__Zaf_Enum_CompareOperatorDefine__(==, name)           \
	__Zaf_Enum_CompareOperatorDefine__(!=, name)           \
	__Zaf_Enum_CompareOperatorDefine__(<, name)            \
	__Zaf_Enum_CompareOperatorDefine__(<=, name)           \
	__Zaf_Enum_CompareOperatorDefine__(>, name)            \
	__Zaf_Enum_CompareOperatorDefine__(>=, name)           \
private:                                                   \
	name##Enum m_enumValue;                                \
};



#define __Zaf_Enum_EnumDefine__(name, type)                \
enum name::name##Enum : type



#define ZafEnum(name, type)                                \
__Zaf_Enum_EnumClassDefine__(name, type)                   \
__Zaf_Enum_EnumDefine__(name, type)



#define ZafFlagEnum(name, type)                                                           \
__Zaf_Enum_EnumClassDefine__(name, type)                                                  \
inline name::name##Enum operator~(name::name##Enum v) {                                   \
	return (name::name##Enum)~((type)v);                                                  \
}                                                                                         \
inline name::name##Enum operator|(name::name##Enum v1, name::name##Enum v2) {             \
	return (name::name##Enum)((type)v1 | (type)v2);                                       \
}                                                                                         \
inline name::name##Enum operator&(name::name##Enum v1, name::name##Enum v2) {             \
	return (name::name##Enum)((type)v1 & (type)v2);                                       \
}                                                                                         \
inline name::name##Enum operator^(name::name##Enum v1, name::name##Enum v2) {             \
	return (name::name##Enum)((type)v1 ^ (type)v2);                                       \
}                                                                                         \
inline name::name##Enum& operator|=(name::name##Enum& v1, name::name##Enum v2) {          \
	v1 = (name::name##Enum)((type)v1 | (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
inline name& operator|=(name& v1, name::name##Enum v2) {                                  \
	v1 = (name::name##Enum)((type)v1 | (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
inline name::name##Enum& operator&=(name::name##Enum& v1, name::name##Enum v2) {          \
	v1 = (name::name##Enum)((type)v1 & (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
inline name& operator&=(name& v1, name::name##Enum v2) {                                  \
	v1 = (name::name##Enum)((type)v1 & (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
inline name::name##Enum& operator^=(name::name##Enum& v1, name::name##Enum v2) {          \
	v1 = (name::name##Enum)((type)v1 ^ (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
inline name& operator^=(name& v1, name::name##Enum v2) {                                  \
	v1 = (name::name##Enum)((type)v1 ^ (type)v2);                                         \
	return v1;                                                                            \
}                                                                                         \
__Zaf_Enum_EnumDefine__(name, type)